package com.shh.rabbitmq.service;

import java.util.Map;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONObject;
import com.rabbitmq.client.Channel;
import com.shh.rabbitmq.dao.OrderDao;
import com.shh.rabbitmq.domain.OrderDO;
/**
 * 费消息有三种回执方法，我们来分析一下每种方法的含义。

1、basicAck

basicAck：表示成功确认，使用此回执方法后，消息会被rabbitmq broker 删除。

void basicAck(long deliveryTag, boolean multiple) 
deliveryTag：表示消息投递序号，每次消费消息或者消息重新投递后，deliveryTag都会增加。手动消息确认模式下，我们可以对指定deliveryTag的消息进行ack、nack、reject等操作。

multiple：是否批量确认，值为 true 则会一次性 ack所有小于当前消息 deliveryTag 的消息。

举个栗子： 假设我先发送三条消息deliveryTag分别是5、6、7，可它们都没有被确认，当我发第四条消息此时deliveryTag为8，multiple设置为 true，会将5、6、7、8的消息全部进行确认。

2、basicNack

basicNack ：表示失败确认，一般在消费消息业务异常时用到此方法，可以将消息重新投递入队列。

void basicNack(long deliveryTag, boolean multiple, boolean requeue)
deliveryTag：表示消息投递序号。

multiple：是否批量确认。

requeue：值为 true 消息将重新入队列。

3、basicReject

basicReject：拒绝消息，与basicNack区别在于不能进行批量操作，其他用法很相似。

void basicReject(long deliveryTag, boolean requeue)
deliveryTag：表示消息投递序号。

requeue：值为 true 消息将重新入队列。
 * @author shaoh
 *
 */
@Service
public class OrderHandleService{
	
	@Autowired
	private OrderDao orderDao;
	
    @RabbitHandler
    @RabbitListener(queues = {"order.direct.queue"})
    public void reviceMessage(Message message, @Headers Map<String, Object> headers, Channel channel) throws Exception {
    	String messageId = message.getMessageProperties().getMessageId();
        String msg = new String(message.getBody(), "UTF-8");
        System.out.println("派单服务平台" + msg + ",消息id:" + messageId);
        OrderDO orderDO = JSONObject.parseObject(msg,OrderDO.class);
        if (StringUtils.isEmpty(orderDO.getOrderNo())) {
            return;
        }
        try {
        	//如果中间发生异常，将消息打入私信队列
//            int num = 2/0;
            //插入派单服务订单表
            orderDao.addOrder(orderDO);
            //手动签收消息,通知mq服务器端删除该消息
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            //丢弃该消息
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
        }
    }
}

